#pragma once

#include "UMLDiagramElement.h"

#include "../uml/Element.h"
#include "UMLStyle.h"

namespace uml {

const bool UMLDiagramElement::isIcon_default_ = false;
UMLDiagramElement::UMLDiagramElement(const QString& umlType)
    : BaseElement(umlType) {}

void UMLDiagramElement::fromJson(const QJsonObject& json, QStringList& errorList) {
    if (json.isEmpty()) {
        return;
    }

    BaseElement::fromJson(json, errorList);
    JsonSerializable::fromJsonArray(modelElements_, "modelElements", json, errorList);
    sharedStyle_ = JsonSerializable::create<UMLStyle>(json.value("sharedStyle"), errorList);

    localStyle_ = JsonSerializable::create<UMLStyle>(json.value("localStyle"), errorList);

    owningElement_ = JsonSerializable::create<UMLDiagramElement>(json.value("owningElement"), errorList);

    isIcon_ = json.value("isIcon").toBool(isIcon_default_);
    JsonSerializable::fromJsonArray(ownedElements_, "ownedElements", json, errorList);
}

void UMLDiagramElement::toJson(QJsonObject& json) {
    BaseElement::toJson(json);
    JsonSerializable::toJsonArray(modelElements_, "modelElements", json);
    if (sharedStyle_) {
        QJsonObject sharedStyle_json;
        sharedStyle_->toJson(sharedStyle_json);
        json.insert("sharedStyle", sharedStyle_json);
    }
    if (localStyle_) {
        QJsonObject localStyle_json;
        localStyle_->toJson(localStyle_json);
        json.insert("localStyle", localStyle_json);
    }
    if (owningElement_) {
        QJsonObject owningElement_json;
        owningElement_->toJson(owningElement_json);
        json.insert("owningElement", owningElement_json);
    }
    if (isIcon_ != isIcon_default_) {
        json.insert("isIcon", isIcon_);
    }
    JsonSerializable::toJsonArray(ownedElements_, "ownedElements", json);
}

/// <summary>
/// modelElements getter
/// Restricts UMLDiagramElements to show UML Elements, rather than other language
/// elements. 
/// </summary>
vector<shared_ptr<Element>>& UMLDiagramElement::modelElements() {
    return modelElements_;
}

/// <summary>
/// sharedStyle getter
/// Restricts shared styles to UMLStyles.
/// </summary>
shared_ptr<UMLStyle> UMLDiagramElement::sharedStyle() const {
    return sharedStyle_;
}

/// <summary>
/// sharedStyle setter
/// Restricts shared styles to UMLStyles.
/// </summary>
void UMLDiagramElement::setSharedStyle(shared_ptr<UMLStyle> value) {
    sharedStyle_ = value;
}

/// <summary>
/// localStyle getter
/// Restricts owned styles to UMLStyles.
/// </summary>
shared_ptr<UMLStyle> UMLDiagramElement::localStyle() const {
    return localStyle_;
}

/// <summary>
/// localStyle setter
/// Restricts owned styles to UMLStyles.
/// </summary>
void UMLDiagramElement::setLocalStyle(shared_ptr<UMLStyle> value) {
    localStyle_ = value;
}

/// <summary>
/// owningElement getter
/// Restricts UMLDiagramElements to be owned by only UMLDiagramElements.
/// </summary>
shared_ptr<UMLDiagramElement> UMLDiagramElement::owningElement() const {
    return owningElement_;
}

/// <summary>
/// owningElement setter
/// Restricts UMLDiagramElements to be owned by only UMLDiagramElements.
/// </summary>
void UMLDiagramElement::setOwningElement(shared_ptr<UMLDiagramElement> value) {
    owningElement_ = value;
}

/// <summary>
/// isIcon getter
/// For modelElements that have an option to be shown with shapes other than
/// rectangles, such as Actors, or with other identifying shapes inside them, such
/// as arrows distinguishing InputPins and OutputPins, or edges that have an option
/// to be shown with lines other than solid with open arrow heads, such as
/// Realization.  A value of true for isIcon indicates the alternative notation
/// shall be shown.
/// </summary>
bool UMLDiagramElement::isIcon() const {
    return isIcon_;
}

/// <summary>
/// isIcon setter
/// For modelElements that have an option to be shown with shapes other than
/// rectangles, such as Actors, or with other identifying shapes inside them, such
/// as arrows distinguishing InputPins and OutputPins, or edges that have an option
/// to be shown with lines other than solid with open arrow heads, such as
/// Realization.  A value of true for isIcon indicates the alternative notation
/// shall be shown.
/// </summary>
void UMLDiagramElement::setIsIcon(bool value) {
    isIcon_ = value;
}

/// <summary>
/// ownedElements getter
/// Restricts UMLDiagramElements to own only UMLDiagramElements.
/// </summary>
vector<shared_ptr<UMLDiagramElement>>& UMLDiagramElement::ownedElements() {
    return ownedElements_;
}

} // namespace uml
